/*
 * Created on May 8, 2004
 */
package dk.aiszone.lang.autosource.generatorobjects;

import java.util.List;

import dk.aiszone.lang.autosource.generatorobjects.helpers.BodyObject;
import dk.aiszone.lang.autosource.generatorobjects.interfaces.BodyContainer;
import dk.aiszone.lang.autosource.generatorobjects.interfaces.BodyContainerWrapper;
import dk.aiszone.lang.autosource.generatorobjects.interfaces.SimpleBlockObject;

/**
 * <p>
 * Representation of a Method.<br>
 * A <code>Method</code> is an extendsion of <code>MethodDeclaration</code> implementing the option of adding lines to a
 * <code>MethodDeclaration</code> giving the declaration a body.<br>
 * The <code>Method</code> will add simple fomatting of the added code. When a line ends with a <b>{ </b> it will add one extra indention until it
 * encounters a line starting with a <b>} </b>.
 * </p>
 * 
 * @see dk.aiszone.lang.autosource.generatorobjects.MethodDeclaration
 * 
 * @author <a href="mailto:ais@mail.dk">Ais</a>
 * @since 1.0
 * @version 1.0.5
 */
public class Method extends MethodDeclaration implements BodyContainerWrapper, Cloneable {

    private BodyContainer body = new BodyObject();

    /**
     * Default constructor for the <code>Method</code> class.<br>
     * Calling this method requires the user to set the <code>declaration</code>, <code>returnType</code> and <code>name</code><br>
     * later on.
     * 
     * @see #setDeclaration(Declaration)
     * @see #setReturnType(Class)
     * @see #setName(String)
     */
    public Method() {
        this(null, null, null);
    }

    /**
     * Constructor for the <code>Method</code> class.
     * 
     * @param declaration
     *            The <code>Declaration</code> of the <code>Method</code>.
     * @param returnType
     *            The return class of the <code>Method</code>.
     * @param name
     *            The name of the <code>Method</code>.
     */
    public Method(Declaration declaration, Class returnType, String name) {
        super(declaration, returnType, name);
    }

    @Override
    public BodyContainer appendToBody(BodyContainer part) {
        return body.appendToBody(part);
    }

    @Override
    public BodyContainer appendToBody(boolean part) {
        return body.appendToBody(part);
    }

    @Override
    public BodyContainer appendToBody(int part) {
        return body.appendToBody(part);
    }

    @Override
    public BodyContainer appendToBody(SimpleBlockObject part) {
        return body.appendToBody(part);
    }

    @Override
    public BodyContainer appendToBody(String part) {
        return body.appendToBody(part);
    }

    @Override
    public BodyContainer appendToBody(StringBuilder part) {
        return body.appendToBody(part);
    }

    @Override
    public BodyContainer appendToBodyEnd(String endPart) {
        return body.appendToBodyEnd(endPart);
    }

    @Override
    public Object clone() {
        Method clone = new Method();

        cloneAttributes(clone);

        clone.body = (BodyContainer)body.clone();

        return clone;
    }

    /**
     * Retrieve the <code>BodyContainer</code> of the <code>Method</code>.
     * 
     * @return The current <code>BodyContainer</code> of the <code>Method</code>.
     */
    public BodyContainer getBody() {
        return body;
    }

    @Override
    public List<SimpleBlockObject> getBodyParts() {
        return body.getBodyParts();
    }

    @Override
    public boolean isBodyEmpty() {
        return body.isBodyEmpty();
    }

    @Override
    public BodyContainer retrieveBodyContainer() {
        return body;
    }

    /**
     * Allows current body to be overwritten by the contents of the supplied <code>String</code>.
     * 
     * @param body
     *            The new body of the <code>Method</code>.
     */
    public void setBody(String body) {
        this.body = new BodyObject();
        this.body.appendToBody(body);
    }

    @Override
    public void setBodyContainer(BodyContainer bodyContainer) {
        this.body = bodyContainer;
    }

    /**
     * <p>
     * Converts the <code>Method</code> to a <code>MethodDeclaration</code>
     * 
     * @return <code>MethodDeclaration</code> of the <code>Method</code>
     */
    public MethodDeclaration toMethodDeclaration() {
        return (MethodDeclaration)super.clone();
    }
}